﻿#ifndef MCSOLVER_H
#define MCSOLVER_H
#define MIN -1000000000000
#include "MCTreeNode.h"
#define MOVE_TIME 15
#include "GreedySolver.cpp"

// 一个uct算法, 但效果很差, 并且现在不能保证work
class MCSolver : public TemplateSolver
{
public:

	Step solve(Frame* frame)
	{
		Board* board = frame->cur_board->get_clone();
		int turn = frame->turn;
		MCTreeNode::nodeCount = 0;
		MCTreeNode::simCount = 0;
		reference_player = turn;

		//以当前棋局情形为根节点
		MCTreeNode* root = new MCTreeNode(board, turn, nullptr, 60-frame->cur_board->get_available_steps().size());

		//在时间限制之前一直搜索
		int oldTime = (int)std::time(0);
		while ((int)std::time(0) - oldTime < MOVE_TIME)
		{
			selectAction(root);
		}
		printf("node count: %d sim count: %d\n", MCTreeNode::nodeCount, MCTreeNode::simCount);
		Step best_step = *(root->getMove());
		delete root;
		return best_step;
	}

	void selectAction(MCTreeNode* root)
	{
		root->nVisits += 1;
		vector<MCTreeNode*>* visited = new vector <MCTreeNode*>();
		MCTreeNode* cur = root;
		visited->push_back(root);
		while (true)
		{
			MCTreeNode* child = select(cur);
			if (child == nullptr)
				break;
			cur = child;
			visited->push_back(cur);
		}

		//生长一层
		cur->expand();

		MCTreeNode* newNode = select(cur);
		if (newNode == nullptr)
			newNode = cur;
		visited->push_back(newNode);

		//int value = simulateFromState(newNode->getBoard(), newNode->getTurn());
		int value = newNode->getBoardWinner(newNode->getBoard(), newNode->getTurn()) == reference_player ? 1 : 0; // 如果这个局面的胜利者是我们, 就得到一分, 反之不得分

		//TODO bug值未更新 7.22 0:27 貌似已经修复, 待测试
		for (MCTreeNode*& node : *visited)
		{
			node->updateStats(value);
		}
	}

	double UCTProcess(MCTreeNode* root, int& Total, int MC_Times)
	{
		root->nVisits++; // 访问次数+1
		if (root->getBoard()->isComplete()) // 如果已经结束了
		{
			if (root->getBoard()->get_winner() == root->turn) // 在这个节点结束, 判定收益
				root->AvgValue = 0;
			else
				root->AvgValue = 1;
			Total++;
			return root->AvgValue;
		}



	}

	//模拟
	int simulateFromState(Board* board, int turn)
	{
		int winner;
		if (board->isComplete()) 
		{
			MCTreeNode::simCount++;
			/*return (board->getScore(turn) - board->getScore(board->toggle_round(turn)));*/
			if (turn == 1 && board->getScore(1) > board->getScore(2))
			{
				return 1 + (board->getScore(turn) - 13.5)*0.02;
			}
			else if(turn == 2 && board->getScore(1) < board->getScore(2))
			{
				return 1 + (board->getScore(board->toggle_round(turn)) - 13.5 )*0.02;
			}
			else if(turn == 1 && board->getScore(1) < board->getScore(2))
			{
				return 0 + (board->getScore(turn) - 13.5) * 0.02;
			}
			else if (turn == 2 && board->getScore(1) > board->getScore(2))
			{
				return 0 + (board->getScore(board->toggle_round(turn)) - 13.5) * 0.02;
			}
		}
		else
		{
			GreedySolver* tempSolver = new GreedySolver();
			Step step = tempSolver->solve(board, turn);
			delete tempSolver;

			Board* nextBoard = board->get_new_board(turn, step.dir, step.x, step.y);
			winner = simulateFromState(nextBoard, (nextBoard->getScore(turn) > board->getScore(turn) ? turn : board->toggle_round(turn)));
			delete nextBoard;
			return winner;
		}
	}

	

	//选举
	MCTreeNode* select(MCTreeNode* cur)
	{
		vector<MCTreeNode*>* children = cur->getChildren();

		if (children == nullptr)
			return nullptr;

		MCTreeNode* selected = nullptr;

		double bestValue = MIN;

		//测试位
		for (MCTreeNode* c : *children)
		{
			double uctValue = c->getValue(cur->getVisits());
			if (uctValue > bestValue)
			{
				selected = c;
				bestValue = uctValue;
			}
		}
		return selected;
	}

};

#endif // !MCSOLVER_H





